#define DISP_INFO

#ifdef DISP_INFO
#include <iostream>
#endif
#include <algorithm>
#include <cmath>
#include "MeshRefine.h"
#include "RefineTria.h"
#include "RefineTetr.h"

using namespace Mesher;

int Mesher::RefineMesh(std::vector<Node> &vR, std::vector<Tria> &vElem, std::vector<bool> &vRefine)
{
    RefineTria worker;

    if (vElem.size() != vRefine.size()) {
        return -1;
    }
#ifdef DISP_INFO
    std::cout << "=============== Refine triangle mesh ===============" << std::endl;
    std::cout << "  Copyright(c) 2021 Wang Yong. All rights reserved. " << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "1. Create the topology of the mesh..." << std::endl;
#endif //  DISP_INFO
    // find all common edge
    worker.fn_FindTriaEdges(vR, vElem);

#ifdef DISP_INFO
    std::cout << "2. Mark elements need to be refined..." << std::endl;
#endif //  DISP_INFO
    // mark the edges need to be splitted
    worker.fn_MarkSplitEdge(vElem, vRefine);
    // adapt the edge to improve the mesh quality
    worker.fn_AdaptTriaEdge(vElem);

#ifdef DISP_INFO
    std::cout << "3. Insert new points in edges..." << std::endl;
#endif //  DISP_INFO
    // insert new point on each edge
    worker.fn_AddEdgesPoint(vElem, vR);

#ifdef DISP_INFO
    std::cout << "4. Refine all marked elements..." << std::endl;
#endif //  DISP_INFO
    // split the element
    worker.fn_SplitEachTria(vElem);

#ifdef DISP_INFO
    std::cout << "============= Mesh refinement finished =============" << std::endl;
#endif //  DISP_INFO

    return SUCCESS;
}

// Refine a tetrahedra mesh
int Mesher::RefineMesh(std::vector<Node> &vR, std::vector<Tetr> &vElem, std::vector<bool> &vRefine)
{
    RefineTetr worker;

    if (vElem.size() != vRefine.size()) {
        return -1;
    }

#ifdef DISP_INFO
    std::cout << "============== Refine tetrahedra mesh ==============" << std::endl;
    std::cout << "  Copyright(c) 2021 Wang Yong. All rights reserved. " << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "1. Create the topology of the mesh..." << std::endl;
#endif //  DISP_INFO
    // find all common edge
    worker.fn_FindTetrEdges(vR, vElem);
    
#ifdef DISP_INFO
    std::cout << "2. Mark elements need to be refined..." << std::endl;
#endif //  DISP_INFO
    // mark the edges need to be splitted
    worker.fn_MarkSplitEdge(vElem, vRefine);
    // adapt the edge to improve the mesh quality
    worker.fn_AdaptTetrEdge(vElem);
    // check and update the split edge number
    worker.fn_CheckTetrType(vElem);


#ifdef DISP_INFO
    std::cout << "3. Insert new points in edges..." << std::endl;
#endif //  DISP_INFO
    // insert new point on each edge
    worker.fn_AddEdgesPoint(vElem, vR);
    
#ifdef DISP_INFO
    std::cout << "4. Refine all marked elements..." << std::endl;
#endif //  DISP_INFO
    // split the element
    worker.fn_SplitEachTetr(vR, vElem);
    // optimize the mesh
    worker.fn_OptimizTetMsh(vR, vElem);

#ifdef DISP_INFO
    std::cout << "============= Mesh refinement finished =============" << std::endl;
#endif //  DISP_INFO

    return SUCCESS;
}
